{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "“所有在头文件中声明于某命名空间的实体，其定义必须出现在同一命名空间中”。实现上有两种等价做法：\n",
    "\n",
    "1. 在 `.cc/.cpp` 里重新打开对应的 `namespace` 再写定义；\n",
    "2. 不打开 `namespace`，而是用完全限定名（如 `myproj::Foo::bar`）来写定义。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 做法 A：在源文件中重新打开相同命名空间"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "// foo.h\n",
    "#pragma once\n",
    "namespace myproj {\n",
    "class Foo {\n",
    "public:\n",
    "  void bar();\n",
    "};\n",
    "void baz();\n",
    "} // namespace myproj"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "// foo.cc\n",
    "#include \"foo.h\"\n",
    "\n",
    "namespace myproj {\n",
    "\n",
    "void Foo::bar() {\n",
    "  // 实现\n",
    "}\n",
    "\n",
    "void baz() {\n",
    "  // 实现\n",
    "}\n",
    "\n",
    "// 仅本文件内部使用的辅助实现，放匿名命名空间\n",
    "namespace {\n",
    "void helper() {}\n",
    "} // anonymous namespace\n",
    "\n",
    "} // namespace myproj"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 做法 B：使用完全限定名，不在源文件显式打开命名空间"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "// foo.cc\n",
    "#include \"foo.h\"\n",
    "\n",
    "void myproj::Foo::bar() {\n",
    "  // 实现\n",
    "}\n",
    "\n",
    "void myproj::baz() {\n",
    "  // 实现\n",
    "}\n",
    "\n",
    "namespace {\n",
    "void helper() {}\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "name": "C++17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
